<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>从 Vue2 迁移 | Vue Router</title>
    <meta name="description" content="Vue.js 的官方路由">
    <link rel="stylesheet" href="static/css/style.720cf281.css">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/Home.50302e7a.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/ui-custom.4cf347f1.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/ui-custom.8de93204.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/AlgoliaSearchBox.80d79d6b.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/app.47b74ea6.js">
    <link rel="modulepreload" href="https://router.vuejs.org/assets/zh_guide_migration_index.md.c448fcd8.lean.js">
    
    <link rel="icon" href="static/picture/logo.png">
  <meta name="wwads-cn-verify" content="7e7757b1e12abcb736ab9a754ffb617a">
  <script src="static/js/thesemetrics@latest.js" async=""></script>
  <meta name="twitter:title" content="从 Vue2 迁移 | Vue Router">
  <meta property="og:title" content="从 Vue2 迁移 | Vue Router">
  </head>
  <body>
    <div id="app"><div class="main-container" data-v-46b24580=""><!----><!--[--><div class="theme"><header class="nav-bar" data-v-675d8756=""><div class="sidebar-button" data-v-675d8756=""><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewbox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path></svg></div><a class="nav-bar-title" href="index1.html" aria-label="Vue Router, back to home" data-v-675d8756="" data-v-4a583abe=""><!----> Vue Router</a><div class="flex-grow" data-v-675d8756=""></div><div class="nav" data-v-675d8756=""><nav class="nav-links" data-v-675d8756="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="index2.html" data-v-b8818f8c="">教程 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="index3.html" data-v-b8818f8c="">API 参考 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">v4.x</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item isExternal" href="index4.html" target="_blank" rel="noopener noreferrer" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">v3.x</span><span class="icon" data-v-bbc27490=""><svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-bbc27490=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">更新日志 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">选择语言</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item" href="index5.html" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">English</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item active" href="" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">中文</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav></div><!--[--><!--[--><div class="algolia-search-box" id="docsearch"></div><!--]--><!--]--></header><aside class="sidebar" data-v-83e92a68=""><nav class="nav-links nav" data-v-83e92a68="" data-v-eab3edfe=""><!--[--><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item active" href="index2.html" data-v-b8818f8c="">教程 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item" href="index3.html" data-v-b8818f8c="">API 参考 <!----></a></div></div><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">v4.x</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item isExternal" href="index4.html" target="_blank" rel="noopener noreferrer" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">v3.x</span><span class="icon" data-v-bbc27490=""><svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-bbc27490=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">更新日志 <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><!--]--><div class="item" data-v-eab3edfe=""><div class="nav-dropdown-link" data-v-eab3edfe="" data-v-56bf3a3f=""><button class="button" data-v-56bf3a3f=""><span class="button-text" data-v-56bf3a3f="">选择语言</span><span class="right button-arrow" data-v-56bf3a3f=""></span></button><ul class="dialog" data-v-56bf3a3f=""><!--[--><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item" href="index5.html" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">English</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f=""><div class="nav-dropdown-link-item" data-v-56bf3a3f="" data-v-bbc27490=""><a class="item active" href="" data-v-bbc27490=""><span class="arrow" data-v-bbc27490=""></span><span class="text" data-v-bbc27490="">中文</span><span class="icon" data-v-bbc27490=""><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe=""><div class="nav-link" data-v-eab3edfe="" data-v-b8818f8c=""><a class="item isExternal" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-b8818f8c="">GitHub <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-b8818f8c=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div></nav><!--[--><!--[--><div class="sponsors sponsors-top" data-v-46b24580=""><span data-v-46b24580="">Platinum Sponsors</span><!--[--><a href="javascript:;" target="_blank" rel="noopener" data-v-46b24580=""><img src="https://posva-sponsors.pages.dev/logos/fincliplogo_black_svg.svg" alt="Finogeeks" data-v-46b24580=""></a><!--]--></div><!--]--><!--]--><ul class="sidebar-links" data-v-83e92a68=""><!--[--><li class="sidebar-link"><a class="sidebar-link-item" href="introduction.html">介绍</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="installation.html">安装</a><!----></li><li class="sidebar-link"><p class="sidebar-link-item">基础</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="index2.html">入门</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="dynamic-matching.html">动态路由匹配</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="route-matching-syntax.html">路由的匹配语法</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="nested-routes.html">嵌套路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="navigation.html">编程式导航</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="named-routes.html">命名路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="named-views.html">命名视图</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="redirect-and-alias.html">重定向和别名</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="passing-props.html">路由组件传参</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="history-mode.html">不同的历史记录模式</a><!----></li></ul></li><li class="sidebar-link"><p class="sidebar-link-item">进阶</p><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="navigation-guards.html">导航守卫</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="meta.html">路由元信息</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="data-fetching.html">数据获取</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="composition-api.html">组合式 API</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="transitions.html">过渡动效</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="scroll-behavior.html">滚动行为</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="lazy-loading.html">路由懒加载</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="extending-router-link.html">扩展 RouterLink</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="navigation-failures.html">导航故障</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="dynamic-routing.html">动态路由</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item active" href="">从 Vue2 迁移</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#破坏性变化">破坏性变化</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#new-router-变成-createrouter">new Router 变成 createRouter</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#新的-history-配置取代-mode">新的 history 配置取代 mode</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#移动了-base-配置">移动了 base 配置</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除了-routeroptions-中的-fallback-属性">删除了 RouterOptions 中的 fallback 属性</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除了-（星标或通配符）路由">删除了 *（星标或通配符）路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#将-onready-改为-isready">将 onReady 改为 isReady</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#scrollbehavior-的变化">scrollBehavior 的变化</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#router-view-、-keep-alive-和-transition">&lt;router-view&gt;、&lt;keep-alive&gt; 和 &lt;transition&gt;</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-link-中的-append-属性">删除 &lt;router-link&gt; 中的 append 属性</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-link-中的-event-和-tag-属性">删除 &lt;router-link&gt; 中的 event 和 tag 属性</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-link-中的-exact-属性">删除 &lt;router-link&gt; 中的 exact 属性</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#忽略-mixins-中的导航守卫">忽略 mixins 中的导航守卫</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-match-改为-router-resolve">删除 router.match 改为 router.resolve</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-getmatchedcomponents">删除 router.getMatchedComponents()</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#所有的导航现在都是异步的">所有的导航现在都是异步的</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-router-app">删除 router.app</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#将内容传递给路由组件的-slot">将内容传递给路由组件的 &lt;slot&gt;</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#将-parent-从路由地址中删除">将 parent 从路由地址中删除</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除-pathtoregexpoptions">删除 pathToRegexpOptions</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#删除未命名的参数">删除未命名的参数</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#history-state-的用法">history.state 的用法</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#options-中需要配置-routes">options 中需要配置 routes</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#不存在的命名路由">不存在的命名路由</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#命名路由缺少必要的-params">命名路由缺少必要的 params</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#带有空-path-的命名子路由不再添加斜线">带有空 path 的命名子路由不再添加斜线</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#route-属性编码">$route 属性编码</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#typescript-变化">TypeScript 变化</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#新功能">新功能</a><!----></li></ul></li><!--]--></ul><!--[--><!--[--><div class="sponsors" data-v-46b24580=""><span data-v-46b24580="">Sponsors</span><!--[--><a href="javascript:;" target="_blank" rel="noopener" data-v-46b24580=""><img src="https://posva-sponsors.pages.dev/logos/vuejobs.svg" alt="VueJobs" data-v-46b24580=""></a><!--]--></div><!--]--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4=""><div class="container" data-v-7eddb2c4=""><!--[--><!--[--><div id="ads-container"><div class="carbon-ads" ref_key="el" data-v-5941b830=""></div></div><!--]--><!--[--><!--]--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4=""><div><h1 id="从-vue2-迁移" tabindex="-1">从 Vue2 迁移 <a class="header-anchor" href="#从-vue2-迁移" aria-hidden="true">#</a></h1><p>在 Vue Router API 从 v3（Vue2）到 v4（Vue3）的重写过程中，大部分的 Vue Router API 都没有变化，但是在迁移你的程序时，你可能会遇到一些破坏性的变化。本指南将帮助你了解为什么会发生这些变化，以及如何调整你的程序，使其与 Vue Router4 兼容。</p><h2 id="破坏性变化" tabindex="-1">破坏性变化 <a class="header-anchor" href="#破坏性变化" aria-hidden="true">#</a></h2><p>变化的顺序是按其用途排列的。因此，建议按照这个清单的顺序进行。</p><h3 id="new-router-变成-createrouter" tabindex="-1">new Router 变成 createRouter <a class="header-anchor" href="#new-router-变成-createrouter" aria-hidden="true">#</a></h3><p>Vue Router 不再是一个类，而是一组函数。现在你不用再写 <code>new Router()</code>，而是要调用 <code>createRouter</code>:</p><div class="language-js"><pre><code><span class="token comment">// 以前是</span>
<span class="token comment">// import Router from &#39;vue-router&#39;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createRouter <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;vue-router&#39;</span>

<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="新的-history-配置取代-mode" tabindex="-1">新的 <code>history</code> 配置取代 <code>mode</code> <a class="header-anchor" href="#新的-history-配置取代-mode" aria-hidden="true">#</a></h3><p><code>mode: &#39;history&#39;</code> 配置已经被一个更灵活的 <code>history</code> 配置所取代。根据你使用的模式，你必须用适当的函数替换它：</p><ul><li><code>&quot;history&quot;</code>: <code>createWebHistory()</code></li><li><code>&quot;hash&quot;</code>: <code>createWebHashHistory()</code></li><li><code>&quot;abstract&quot;</code>: <code>createMemoryHistory()</code></li></ul><p>下面是一个完整的代码段：</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> createRouter<span class="token punctuation">,</span> createWebHistory <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;vue-router&#39;</span>
<span class="token comment">// 还有 createWebHashHistory 和 createMemoryHistory</span>

<span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">history</span><span class="token operator">:</span> <span class="token function">createWebHistory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token literal-property property">routes</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>在 SSR 上使用时，你需要手动传递相应的 history：</p><div class="language-js"><pre><code><span class="token comment">// router.js</span>
<span class="token keyword">let</span> history <span class="token operator">=</span> isServer <span class="token operator">?</span> <span class="token function">createMemoryHistory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">createWebHistory</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> router <span class="token operator">=</span> <span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> routes<span class="token punctuation">,</span> history <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token comment">// 在你的 server-entry.js 中的某个地方</span>
router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>url<span class="token punctuation">)</span> <span class="token comment">// 请求 url</span>
router<span class="token punctuation">.</span><span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 处理请求</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p><strong>原因</strong>：为未使用的 history 启用摇树，以及为高级用例（如原生解决方案）实现自定义 history。</p><h3 id="移动了-base-配置" tabindex="-1">移动了 <code>base</code> 配置 <a class="header-anchor" href="#移动了-base-配置" aria-hidden="true">#</a></h3><p>现在，<code>base</code> 配置被作为 <code>createWebHistory</code> (其他 history 也一样)的第一个参数传递：</p><div class="language-js"><pre><code><span class="token keyword">import</span> <span class="token punctuation">{</span> createRouter<span class="token punctuation">,</span> createWebHistory <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&#39;vue-router&#39;</span>
<span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">history</span><span class="token operator">:</span> <span class="token function">createWebHistory</span><span class="token punctuation">(</span><span class="token string">&#39;/base-directory/&#39;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token literal-property property">routes</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="删除了-routeroptions-中的-fallback-属性" tabindex="-1">删除了 <code>RouterOptions</code> 中的 <code>fallback</code> 属性 <a class="header-anchor" href="#删除了-routeroptions-中的-fallback-属性" aria-hidden="true">#</a></h3><p>创建路由时不再支持 <code>fallback</code> 属性：</p><div class="language-diff"><pre><code><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line">new VueRouter({
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">createRouter({
</span></span><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line">  fallback: false,
</span></span>// other options...
})
</code></pre></div><p><strong>原因</strong>: Vue支持的所有浏览器都支持 <a href="javascript:;" target="_blank" rel="noopener noreferrer">HTML5 History API</a>，因此我们不再需要使用 <code>location.hash</code>，而可以直接使用 <code>history.pushState()</code>。</p><h3 id="删除了-（星标或通配符）路由" tabindex="-1">删除了 <code>*</code>（星标或通配符）路由 <a class="header-anchor" href="#删除了-（星标或通配符）路由" aria-hidden="true">#</a></h3><p>现在必须使用自定义的 regex 参数来定义所有路由(<code>*</code>、<code>/*</code>)：</p><div class="language-js"><pre><code><span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token comment">// pathMatch 是参数的名称，例如，跳转到 /not/found 会得到</span>
  <span class="token comment">// { params: { pathMatch: [&#39;not&#39;, &#39;found&#39;] } }</span>
  <span class="token comment">// 这要归功于最后一个 *，意思是重复的参数，如果你</span>
  <span class="token comment">// 打算直接使用未匹配的路径名称导航到该路径，这是必要的</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/:pathMatch(.*)*&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;not-found&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> NotFound <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token comment">// 如果你省略了最后的 `*`，在解析或跳转时，参数中的 `/` 字符将被编码</span>
  <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/:pathMatch(.*)&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;bad-not-found&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> NotFound <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
<span class="token comment">// 如果使用命名路由，不好的例子：</span>
router<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;bad-not-found&#39;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">pathMatch</span><span class="token operator">:</span> <span class="token string">&#39;not/found&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span>href <span class="token comment">// &#39;/not%2Ffound&#39;</span>
<span class="token comment">// 好的例子:</span>
router<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;not-found&#39;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">params</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token literal-property property">pathMatch</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&#39;not&#39;</span><span class="token punctuation">,</span> <span class="token string">&#39;found&#39;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span>href <span class="token comment">// &#39;/not/found&#39;</span>
</code></pre></div><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>如果你不打算使用其名称直接跳转到未找到的路由，则无需为重复的参数添加 <code>*</code>。如果你调用 <code>router.push(&#39;/not/found/url&#39;)</code>，它将提供正确的 <code>pathMatch</code> 参数。</p></div><p><strong>原因</strong>：Vue Router 不再使用 <code>path-to-regexp</code>，而是实现了自己的解析系统，允许路由排序并实现动态路由。由于我们通常在每个项目中只添加一个通配符路由，所以支持 <code>*</code> 的特殊语法并没有太大的好处。参数的编码是跨路由的，无一例外，让事情更容易预测。</p><h3 id="将-onready-改为-isready" tabindex="-1">将 <code>onReady</code> 改为 <code>isReady</code> <a class="header-anchor" href="#将-onready-改为-isready" aria-hidden="true">#</a></h3><p>现有的 <code>router.onReady()</code> 函数已被 <code>router.isReady()</code> 取代，该函数不接受任何参数并返回一个 Promise：</p><div class="language-js"><pre><code><span class="token comment">// 将</span>
router<span class="token punctuation">.</span><span class="token function">onReady</span><span class="token punctuation">(</span>onSuccess<span class="token punctuation">,</span> onError<span class="token punctuation">)</span>
<span class="token comment">// 替换成</span>
router<span class="token punctuation">.</span><span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>onSuccess<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span>onError<span class="token punctuation">)</span>
<span class="token comment">// 或者使用 await:</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
  <span class="token keyword">await</span> router<span class="token punctuation">.</span><span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token comment">// 成功</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 报错</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="scrollbehavior-的变化" tabindex="-1"><code>scrollBehavior</code> 的变化 <a class="header-anchor" href="#scrollbehavior-的变化" aria-hidden="true">#</a></h3><p><code>scrollBehavior</code> 中返回的对象与 <a href="javascript:;" target="_blank" rel="noopener noreferrer"><code>ScrollToOptions</code></a> 类似：<code>x</code> 改名为 <code>left</code>，<code>y</code> 改名为 <code>top</code>。详见 <a href="javascript:;" target="_blank" rel="noopener noreferrer">RFC</a>。</p><p><strong>原因</strong>：使该对象类似于 <code>ScrollToOptions</code>，以使其感觉更像原生 JS API，并有可能启用将来的新配置。</p><h3 id="router-view-、-keep-alive-和-transition" tabindex="-1"><code>&lt;router-view&gt;</code>、<code>&lt;keep-alive&gt;</code> 和 <code>&lt;transition&gt;</code> <a class="header-anchor" href="#router-view-、-keep-alive-和-transition" aria-hidden="true">#</a></h3><p><code>transition</code> 和 <code>keep-alive</code> 现在必须通过 <code>v-slot</code> API 在 <code>RouterView</code> <strong>内部</strong>使用：</p><div class="language-vue"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-view</span> <span class="token attr-name">v-slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>{ Component }<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>transition</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>keep-alive</span><span class="token punctuation">&gt;</span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>component</span> <span class="token attr-name">:is</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>Component<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>keep-alive</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>transition</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-view</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p><strong>原因</strong>: 这是一个必要的变化。详见 <a href="javascript:;" target="_blank" rel="noopener noreferrer">related RFC</a>.</p><h3 id="删除-router-link-中的-append-属性" tabindex="-1">删除 <code>&lt;router-link&gt;</code> 中的 <code>append</code> 属性 <a class="header-anchor" href="#删除-router-link-中的-append-属性" aria-hidden="true">#</a></h3><p><code>&lt;router-link&gt;</code> 中的 <code>append</code> 属性已被删除。你可以手动将值设置到现有的 <code>path</code> 中：</p><div class="language-html"><pre><code>将
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>child-route<span class="token punctuation">&quot;</span></span> <span class="token attr-name">append</span><span class="token punctuation">&gt;</span></span>to relative child<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
替换成
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> <span class="token attr-name">:to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>append($route.path, <span class="token punctuation">&#39;</span>child-route<span class="token punctuation">&#39;</span>)<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  to relative child
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>你必须在 <em>App</em> 实例上定义一个全局的 <code>append</code> 函数：</p><div class="language-js"><pre><code>app<span class="token punctuation">.</span>config<span class="token punctuation">.</span>globalProperties<span class="token punctuation">.</span><span class="token function-variable function">append</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">path<span class="token punctuation">,</span> pathToAppend</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span>
  path <span class="token operator">+</span> <span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">endsWith</span><span class="token punctuation">(</span><span class="token string">&#39;/&#39;</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token string">&#39;&#39;</span> <span class="token operator">:</span> <span class="token string">&#39;/&#39;</span><span class="token punctuation">)</span> <span class="token operator">+</span> pathToAppend
</code></pre></div><p><strong>原因</strong>：<code>append</code> 使用频率不高，用户可以很容易地实现。</p><h3 id="删除-router-link-中的-event-和-tag-属性" tabindex="-1">删除 <code>&lt;router-link&gt;</code> 中的 <code>event</code> 和 <code>tag</code> 属性 <a class="header-anchor" href="#删除-router-link-中的-event-和-tag-属性" aria-hidden="true">#</a></h3><p><code>&lt;router-link&gt;</code> 中的 <code>event</code> 和 <code>tag</code> 属性都已被删除。你可以使用 <a href="index3.html#router-link-s-v-slot"><code>v-slot</code> API</a> 来完全定制 <code>&lt;router-link&gt;</code>：</p><div class="language-html"><pre><code>将
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>/about<span class="token punctuation">&quot;</span></span> <span class="token attr-name">tag</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>span<span class="token punctuation">&quot;</span></span> <span class="token attr-name">event</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>dblclick<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>About Us<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
替换成
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-link</span> <span class="token attr-name">to</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>/about<span class="token punctuation">&quot;</span></span> <span class="token attr-name">custom</span> <span class="token attr-name">v-slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>{ navigate }<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>navigate<span class="token punctuation">&quot;</span></span> <span class="token attr-name">@keypress.enter</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>navigate<span class="token punctuation">&quot;</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>link<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>About Us<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-link</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p><strong>原因</strong>：这些属性经常一起使用，以使用与 <code>&lt;a&gt;</code> 标签不同的东西，但这些属性是在 <code>v-slot</code> API 之前引入的，并且没有足够的使用，因此没有足够的理由为每个人增加 bundle 包的大小。</p><h3 id="删除-router-link-中的-exact-属性" tabindex="-1">删除 <code>&lt;router-link&gt;</code> 中的 <code>exact</code> 属性 <a class="header-anchor" href="#删除-router-link-中的-exact-属性" aria-hidden="true">#</a></h3><p><code>exact</code> 属性已被删除，因为不再存在要修复的警告，所以你应该能够安全地删除它。但，有两件事你应该注意：</p><ul><li>路由现在是基于它们所代表的路由记录来激活的，而不是路由地址对象及其 <code>path</code>、<code>query</code> 和 <code>hash</code> 属性来激活的</li><li>只匹配 <code>path</code> 部分，<code>query</code> 和 <code>hash</code> 不再考虑</li></ul><p>如果你想自定义这种行为，例如考虑到 <code>hash</code> 部分，你应该使用 <a href="index8.html#router-link-s-v-slot" target="_blank" rel="noopener noreferrer"><code>v-slot</code> API</a> 来扩展<code>&lt;router-link&gt;</code>。</p><p><strong>原因</strong>: 详见 <a href="javascript:;" target="_blank" rel="noopener noreferrer">RFC about active matching</a>。</p><h3 id="忽略-mixins-中的导航守卫" tabindex="-1">忽略 mixins 中的导航守卫 <a class="header-anchor" href="#忽略-mixins-中的导航守卫" aria-hidden="true">#</a></h3><p>目前不支持 mixins 中的导航守卫，你可以在 <a href="javascript:;" target="_blank" rel="noopener noreferrer">vue-router#454</a> 追踪它的支持情况。</p><h3 id="删除-router-match-改为-router-resolve" tabindex="-1">删除 <code>router.match</code> 改为 <code>router.resolve</code> <a class="header-anchor" href="#删除-router-match-改为-router-resolve" aria-hidden="true">#</a></h3><p><code>router.match</code> 和 <code>router.resolve</code> 已合并到 <code>router.resolve</code> 中，签名略有不同。<a href="index3.html#resolve">详见 API</a>。</p><p><strong>原因</strong>：将用于同一目的的多种方法统一起来。</p><h3 id="删除-router-getmatchedcomponents" tabindex="-1">删除 <code>router.getMatchedComponents()</code> <a class="header-anchor" href="#删除-router-getmatchedcomponents" aria-hidden="true">#</a></h3><p><code>router.getMatchedComponents</code> 方法现在被删除，因为匹配的组件可以从 <code>router.currentRoute.value.matched</code> 中获取：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span>currentRoute<span class="token punctuation">.</span>value<span class="token punctuation">.</span>matched<span class="token punctuation">.</span><span class="token function">flatMap</span><span class="token punctuation">(</span><span class="token parameter">record</span> <span class="token operator">=&gt;</span>
  Object<span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span>record<span class="token punctuation">.</span>components<span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre></div><p><strong>原因</strong>：这个方法只在 SSR 中使用，并且是用户一行就能完成的操作。</p><h3 id="所有的导航现在都是异步的" tabindex="-1"><strong>所有</strong>的导航现在都是异步的 <a class="header-anchor" href="#所有的导航现在都是异步的" aria-hidden="true">#</a></h3><p>所有的导航，包括第一个导航，现在都是异步的，这意味着，如果你使用一个 <code>transition</code>，你可能需要等待路由 <em>ready</em> 好后再挂载程序：</p><div class="language-js"><pre><code>app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>router<span class="token punctuation">)</span>
<span class="token comment">// 注意：在服务器端，你需要手动跳转到初始地址。</span>
router<span class="token punctuation">.</span><span class="token function">isReady</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> app<span class="token punctuation">.</span><span class="token function">mount</span><span class="token punctuation">(</span><span class="token string">&#39;#app&#39;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></div><p>否则会有一个初始过渡，就像你提供了 <code>appear</code> 属性到 <code>transition</code> 一样，因为路由会显示它的初始地址（什么都没有），然后显示第一个地址。</p><p>请注意，<strong>如果在初始导航时有导航守卫</strong>，你可能不想阻止程序渲染，直到它们被解析，除非你正在进行服务器端渲染。否则，在这种情况下，不等待路由准备好挂载应用会产生与 Vue2 中相同的结果。</p><h3 id="删除-router-app" tabindex="-1">删除 <code>router.app</code> <a class="header-anchor" href="#删除-router-app" aria-hidden="true">#</a></h3><p><code>router.app</code> 用于表示注入路由的最后一个根组件（Vue 实例）。Vue Router 现在可以被多个 Vue 程序同时安全使用。你仍然可以在使用路由时添加它：</p><div class="language-js"><pre><code>app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>router<span class="token punctuation">)</span>
router<span class="token punctuation">.</span>app <span class="token operator">=</span> app
</code></pre></div><p>你也可以扩展 <code>Router</code> 接口的 TypeScript 定义来添加 <code>app</code> 属性。</p><p><strong>原因</strong>：Vue3 写的程序不能在 Vue2 中使用，现在我们使用同一个 Router 实例来支持多个程序，因此拥有 <code>app</code> 属性可能会产生误导，因为它是程序而不是根实例。</p><h3 id="将内容传递给路由组件的-slot" tabindex="-1">将内容传递给路由组件的 <code>&lt;slot&gt;</code> <a class="header-anchor" href="#将内容传递给路由组件的-slot" aria-hidden="true">#</a></h3><p>之前你可以直接传递一个模板，通过嵌套在 <code>&lt;router-view&gt;</code> 组件下，由路由组件的 <code>&lt;slot&gt;</code> 来渲染：</p><div class="language-html"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-view</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>In Vue Router 3, I render inside the route component<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-view</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>由于 <code>&lt;router-view&gt;</code> 引入了 <code>v-slot</code> API，你必须使用 <code>v-slot</code> API 将其传递给 <code>&lt;component&gt;</code>：</p><div class="language-html"><pre><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>router-view</span> <span class="token attr-name">v-slot</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>{ Component }<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>component</span> <span class="token attr-name">:is</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>Component<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>In Vue Router 3, I render inside the route component<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>component</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>router-view</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><h3 id="将-parent-从路由地址中删除" tabindex="-1">将 <code>parent</code> 从路由地址中删除 <a class="header-anchor" href="#将-parent-从路由地址中删除" aria-hidden="true">#</a></h3><p><code>parent</code> 属性已从标准化路由地址（<code>this.$route</code> 和 <code>router.resolve</code> 返回的对象）中删除。你仍然可以通过 <code>matched</code> 数组访问它：</p><div class="language-js"><pre><code><span class="token keyword">const</span> parent <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$route<span class="token punctuation">.</span>matched<span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span>$route<span class="token punctuation">.</span>matched<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">]</span>
</code></pre></div><p><strong>原因</strong>：同时存在 <code>parent</code> 和 <code>children</code> 会造成不必要的循环引用，而属性可以通过 <code>matched</code> 来检索。</p><h3 id="删除-pathtoregexpoptions" tabindex="-1">删除 <code>pathToRegexpOptions</code> <a class="header-anchor" href="#删除-pathtoregexpoptions" aria-hidden="true">#</a></h3><p>路由的 <code>pathToRegexpOptions</code> 和 <code>caseSensitive</code> 属性已被 <code>createRouter()</code> 的 <code>sensitive</code> 和 <code>strict</code> 配置取代。现在，当使用 <code>createRouter()</code> 创建路由时，它们也可以直接传递。<code>path-to-regexp</code> 的任何其他特定配置已被删除，因为 <code>path-to-regexp</code> 已不再用于解析路径。</p><h3 id="删除未命名的参数" tabindex="-1">删除未命名的参数 <a class="header-anchor" href="#删除未命名的参数" aria-hidden="true">#</a></h3><p>由于取消了 <code>path-to-regexp</code>，所以不再支持未命名的参数：</p><ul><li><code>/foo(/foo)?/suffix</code> 变成 <code>/foo/:_(foo)?/suffix</code></li><li><code>/foo(foo)?</code> 变成 <code>/foo:_(foo)?</code></li><li><code>/foo/(.*)</code> 变成 <code>/foo/:_(.*)</code></li></ul><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>请注意，你可以使用任何名称代替 <code>_</code> 作为参数。重点是要提供一个名字。</p></div><h3 id="history-state-的用法" tabindex="-1"><code>history.state</code> 的用法 <a class="header-anchor" href="#history-state-的用法" aria-hidden="true">#</a></h3><p>Vue Router 将信息保存在 <code>history.state</code> 上。如果你有任何手动调用 <code>history.pushState()</code> 的代码，你应该避免它，或者用的 <code>router.push()</code> 和 <code>history.replaceState()</code> 进行重构：</p><div class="language-js"><pre><code><span class="token comment">// 将</span>
history<span class="token punctuation">.</span><span class="token function">pushState</span><span class="token punctuation">(</span>myState<span class="token punctuation">,</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span>
<span class="token comment">// 替换成</span>
<span class="token keyword">await</span> router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span>
history<span class="token punctuation">.</span><span class="token function">replaceState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token operator">...</span>history<span class="token punctuation">.</span>state<span class="token punctuation">,</span> <span class="token operator">...</span>myState <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">)</span>
</code></pre></div><p>同样，如果你在调用 <code>history.replaceState()</code> 时没有保留当前状态，你需要传递当前 <code>history.state</code>：</p><div class="language-js"><pre><code><span class="token comment">// 将</span>
history<span class="token punctuation">.</span><span class="token function">replaceState</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span>
<span class="token comment">// 替换成</span>
history<span class="token punctuation">.</span><span class="token function">replaceState</span><span class="token punctuation">(</span>history<span class="token punctuation">.</span>state<span class="token punctuation">,</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span>
</code></pre></div><p><strong>原因</strong>：我们使用历史状态来保存导航信息，如滚动位置，以前的地址等。</p><h3 id="options-中需要配置-routes" tabindex="-1"><code>options</code> 中需要配置 <code>routes</code> <a class="header-anchor" href="#options-中需要配置-routes" aria-hidden="true">#</a></h3><p><code>options</code> 中的 <code>routes</code> 属性现在是必需的。</p><div class="language-js"><pre><code><span class="token function">createRouter</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">routes</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p><strong>原因</strong>：路由的设计是为了创建路由，尽管你可以在以后添加它们。在大多数情况下，你至少需要一条路由，一般每个应用都会编写一次。</p><h3 id="不存在的命名路由" tabindex="-1">不存在的命名路由 <a class="header-anchor" href="#不存在的命名路由" aria-hidden="true">#</a></h3><p>跳转或解析不存在的命名路由会产生错误：</p><div class="language-js"><pre><code><span class="token comment">// 哎呀，我们的名字打错了</span>
router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;homee&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 报错</span>
router<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;homee&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// 报错</span>
</code></pre></div><p><strong>原因</strong>：以前，路由会导航到 <code>/</code>，但不显示任何内容（而不是主页）。抛出一个错误更有意义，因为我们不能生成一个有效的 URL 进行导航</p><h3 id="命名路由缺少必要的-params" tabindex="-1">命名路由缺少必要的 <code>params</code> <a class="header-anchor" href="#命名路由缺少必要的-params" aria-hidden="true">#</a></h3><p>在没有传递所需参数的情况下跳转或解析命名路由，会产生错误：</p><div class="language-js"><pre><code><span class="token comment">// 给与以下路由:</span>
<span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/users/:id&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;user&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> UserDetails <span class="token punctuation">}</span><span class="token punctuation">]</span>

<span class="token comment">// 缺少 `id` 参数会失败</span>
router<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;user&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
router<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;user&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p><strong>原因</strong>：同上。</p><h3 id="带有空-path-的命名子路由不再添加斜线" tabindex="-1">带有空 <code>path</code> 的命名子路由不再添加斜线 <a class="header-anchor" href="#带有空-path-的命名子路由不再添加斜线" aria-hidden="true">#</a></h3><p>给予任何空 <code>path</code> 的嵌套命名路由：</p><div class="language-js"><pre><code><span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/dashboard&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;dashboard-parent&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">component</span><span class="token operator">:</span> DashboardParent
    <span class="token literal-property property">children</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;dashboard&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> DashboardDefault <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;settings&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;dashboard-settings&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> DashboardSettings <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code></pre></div><p>现在，导航或解析到命名的路由 <code>dashboard</code> 时，会产生一个<strong>不带斜线的 URL</strong>：</p><div class="language-js"><pre><code>router<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">&#39;dashboard&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span>href <span class="token comment">// &#39;/dashboard&#39;</span>
</code></pre></div><p>这对子级 <code>redirect</code> 有重要的副作用，如下所示：</p><div class="language-js"><pre><code><span class="token keyword">const</span> routes <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">{</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;/parent&#39;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">component</span><span class="token operator">:</span> Parent<span class="token punctuation">,</span>
    <span class="token literal-property property">children</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token comment">// 现在将重定向到 `/home` 而不是 `/parent/home`</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">redirect</span><span class="token operator">:</span> <span class="token string">&#39;home&#39;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">{</span> <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token string">&#39;home&#39;</span><span class="token punctuation">,</span> <span class="token literal-property property">component</span><span class="token operator">:</span> Home <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span>
</code></pre></div><p>请注意，如果 <code>path</code> 是 <code>/parent/</code>，这也可以，因为 <code>home</code> 到 <code>/parent/</code> 的相对地址确实是 <code>/parent/home</code>，但 <code>home</code> 到 <code>/parent</code> 的相对地址是 <code>/home</code>。</p><p><strong>原因</strong>：这是为了使尾部的斜线行为保持一致：默认情况下，所有路由都允许使用尾部的斜线。可以通过使用 <code>strict</code> 配置和手动添加(或不添加)斜线来禁用它。</p><h3 id="route-属性编码" tabindex="-1"><code>$route</code> 属性编码 <a class="header-anchor" href="#route-属性编码" aria-hidden="true">#</a></h3><p>无论在哪里启动导航，<code>params</code>、<code>query</code>和 <code>hash</code> 中的解码值现在都是一致的（旧的浏览器仍然会产生未编码的 <code>path</code> 和 <code>fullPath</code>）。初始导航应产生与应用内部导航相同的结果。</p><p>给定任何<a href="index3.html#routelocationnormalized">规范化的路由地址</a>:</p><ul><li><code>hash</code> 现在被解码了，这样就可以复制过来。<code>router.push({ hash: $route.hash })</code> 可以直接用于 <a href="index3.html#scrollbehavior">scrollBehavior</a> 的 <code>el</code> 配置中。</li><li>当使用 <code>push</code>、<code>resolve</code> 和 <code>replace</code> 并在对象中提供 <code>string</code> 地址或 <code>path</code> 属性时，<strong>必须进行编码</strong>(像以前的版本一样)。另一方面，<code>params</code>、<code>query</code> 和 <code>hash</code> 必须以未编码的版本提供。</li><li>斜线字符(<code>/</code>)现在已在 <code>params</code> 内正确解码，同时仍在 URL 上产生一个编码版本：<code>%2F</code>。</li></ul><p><strong>原因</strong>：这样，在调用 <code>router.push()</code> 和 <code>router.resolve()</code> 时，可以很容易地复制一个地址的现有属性，并使产生的路由地址在各浏览器之间保持一致。<code>router.push()</code> 现在是幂等的，这意味着调用 <code>router.push(route.fullPath)</code>、<code>router.push({ hash: route.hash })</code>、<code>router.push({ query: route.query })</code> 和<code>router.push({ params: route.params })</code> 不会产生额外的编码。</p><h3 id="typescript-变化" tabindex="-1">TypeScript 变化 <a class="header-anchor" href="#typescript-变化" aria-hidden="true">#</a></h3><p>为了使类型更一致，更有表现力，有些类型被重新命名：</p><table><thead><tr><th><code>vue-router@3</code></th><th><code>vue-router@4</code></th></tr></thead><tbody><tr><td>RouteConfig</td><td>RouteRecordRaw</td></tr><tr><td>Location</td><td>RouteLocation</td></tr><tr><td>Route</td><td>RouteLocationNormalized</td></tr></tbody></table><h2 id="新功能" tabindex="-1">新功能 <a class="header-anchor" href="#新功能" aria-hidden="true">#</a></h2><p>Vue Router4 中需要关注的一些新功能包括：</p><ul><li><a href="dynamic-routing.html">动态路由</a></li><li><a href="composition-api.html">组合式 API</a></li></ul></div></div><footer class="page-footer" data-v-7eddb2c4="" data-v-fb8d84c6=""><div class="edit" data-v-fb8d84c6=""><div class="edit-link" data-v-fb8d84c6="" data-v-1ed99556=""><a class="link" href="javascript:;" target="_blank" rel="noopener noreferrer" data-v-1ed99556="">Suggest changes to this page <svg class="icon outbound icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15" data-v-1ed99556=""><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></div><div class="updated" data-v-fb8d84c6=""><!----></div></footer><div class="next-and-prev-link" data-v-7eddb2c4="" data-v-38ede35f=""><div class="container" data-v-38ede35f=""><div class="prev" data-v-38ede35f=""><a class="link" href="dynamic-routing.html" data-v-38ede35f=""><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon icon-prev" data-v-38ede35f=""><path d="M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z"></path></svg><span class="text" data-v-38ede35f="">动态路由</span></a></div><div class="next" data-v-38ede35f=""><!----></div></div></div><!--[--><!--[--><!--]--><!--[--><div class="buy-sell-ads" data-v-4ce5ad17=""><div class="bsa-cpc" data-v-4ce5ad17=""></div></div><!--]--><!--]--></div></main></div><!----><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"api_index.md\":\"d2104c47\",\"guide_advanced_composition-api.md\":\"c4a35a0b\",\"guide_advanced_data-fetching.md\":\"b840e67c\",\"guide_advanced_dynamic-routing.md\":\"652f0e44\",\"guide_advanced_extending-router-link.md\":\"9af8914a\",\"guide_advanced_lazy-loading.md\":\"8d710c99\",\"guide_advanced_meta.md\":\"a024ec3d\",\"guide_advanced_navigation-failures.md\":\"57e1a0e2\",\"guide_advanced_navigation-guards.md\":\"7d263b2b\",\"guide_advanced_scroll-behavior.md\":\"84f7daa3\",\"guide_advanced_transitions.md\":\"85553476\",\"guide_essentials_dynamic-matching.md\":\"fa6babaa\",\"guide_essentials_history-mode.md\":\"56f164ed\",\"guide_essentials_named-routes.md\":\"94d29abc\",\"guide_essentials_named-views.md\":\"c0d13d46\",\"guide_essentials_navigation.md\":\"c1db3764\",\"guide_essentials_nested-routes.md\":\"0c92c29e\",\"guide_essentials_passing-props.md\":\"c283ba51\",\"guide_essentials_redirect-and-alias.md\":\"ff823362\",\"guide_essentials_route-matching-syntax.md\":\"8d709abb\",\"guide_index.md\":\"adc6171f\",\"guide_migration_index.md\":\"b3d45cf2\",\"index.md\":\"58761df1\",\"installation.md\":\"80dcd302\",\"introduction.md\":\"e6a9eb47\",\"zh_api_index.md\":\"9540fde2\",\"zh_guide_advanced_composition-api.md\":\"c9cfee63\",\"zh_guide_advanced_data-fetching.md\":\"c83aef48\",\"zh_guide_advanced_dynamic-routing.md\":\"10e27a0f\",\"zh_guide_advanced_extending-router-link.md\":\"4de5dd4e\",\"zh_guide_advanced_lazy-loading.md\":\"bc3ba5ac\",\"zh_guide_advanced_meta.md\":\"9802cc2e\",\"zh_guide_advanced_navigation-failures.md\":\"02c8440d\",\"zh_guide_advanced_navigation-guards.md\":\"2c59c5ad\",\"zh_guide_advanced_scroll-behavior.md\":\"22a11e87\",\"zh_guide_advanced_transitions.md\":\"f4039441\",\"zh_guide_essentials_dynamic-matching.md\":\"e6594e44\",\"zh_guide_essentials_history-mode.md\":\"beb89b31\",\"zh_guide_essentials_named-routes.md\":\"66c05082\",\"zh_guide_essentials_named-views.md\":\"9aae5c1b\",\"zh_guide_essentials_navigation.md\":\"c0faee1f\",\"zh_guide_essentials_nested-routes.md\":\"e1852582\",\"zh_guide_essentials_passing-props.md\":\"030d2081\",\"zh_guide_essentials_redirect-and-alias.md\":\"ea0856be\",\"zh_guide_essentials_route-matching-syntax.md\":\"e907166f\",\"zh_guide_index.md\":\"bb134cde\",\"zh_guide_migration_index.md\":\"c448fcd8\",\"zh_index.md\":\"90ac17e3\",\"zh_installation.md\":\"7a5d9568\",\"zh_introduction.md\":\"6a2f4e36\"}")</script>
    <script type="module" async="" src="static/js/app.47b74ea6.js"></script>
    
  </body>
</html>